package yartiss.engine.simulation.system.taskset.generation.task;

import java.util.Random;

import yartiss.engine.simulation.system.ITask;
import yartiss.engine.simulation.system.taskset.generation.ITaskGenerator;

/**
 * AbstractEnergyTaskGenerator is an abstract class that implements the
 * ITaskGenerator interface, and generates real-time tasks with energy profile.
 * 
 * @author Manar Qamhieh
 * 
 */
public abstract class AbstractEnergyTaskGenerator implements ITaskGenerator {
	protected final static int MAX_PERIOD = 1000;
	protected final Random random = new Random();
	private static int CURRENT_PRIORITY = 1;

	@Override
	public ITask generate(double utilization, double energyUtilization,
			long Pr, boolean offset, int deadlineModel, int maxProc) {

		long start = 0, period = 0, wcet = 0, wcee = 0, x;
		long bestPeriod = 0, bestWcet = 0, bestWcee = 0;
		double ue = 0, bestDiff = Double.MAX_VALUE;

		for (int i = 0; i < MAX_PERIOD; i++) {

			period = nextInt(1, MAX_PERIOD);
			wcet = Math.max(1, (long) (period * utilization));
			utilization = ((double) wcet) / period;
			x = (long) Math.max(1, (energyUtilization / utilization - 1) * Pr);
			wcee = (Pr + x) * wcet;

			ue = ((double) wcee) / (period * Pr);
			double diff = Math.abs(energyUtilization - ue);
			if (diff < bestDiff) {
				bestPeriod = period;
				bestWcet = wcet;
				bestWcee = wcee;
				bestDiff = diff;
			}
			if (diff < 0.05)
				break;
		}

		period = bestPeriod;
		wcet = bestWcet;
		wcee = bestWcee;

		int priority = CURRENT_PRIORITY++;
		if (CURRENT_PRIORITY > 100)
			CURRENT_PRIORITY = 1;

		long deadline = period; // implicit deadline

		if (deadlineModel < 0) { // constrained deadline
			deadline = nextInt((int) wcet, (int) period);
		} else if (deadlineModel > 0) { // arbitrary deadline
			deadline = nextInt(1, MAX_PERIOD);
		}

		if (offset) {
			start = nextInt(0, (int) period);
		}

		return generate(start, wcet, wcee, period, deadline, priority);
	}

	protected abstract ITask generate(long start, long wcet, long wcee,
			long period, long deadline, int priority);

	protected int nextInt(int from, int to) {
		return from + random.nextInt(to - from + 1);
	}
}
